home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacTech 1 to 12
/
MacTech-vol-1-12.toast
/
Reference
/
the cmsp digests ('94-'97)
/
csmp digest Vol 3 No 108
< prev
next >
Wrap
Text File
|
1995-08-25
|
78KB
|
1,867 lines
C.S.M.P. Digest Thu, 24 Aug 95 Volume 3 : Issue 108
Today's Topics:
Asynchronous File I-O
Saving and restoring current drawing port - necessary?
Where are my command line arguments?
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet newsgroups
comp.sys.mac.programmer.help, csmp.tools and csmp.misc. It is designed for
people who read news semi-regularly and want an archive of the discussions.
If you don't know what a newsgroup is, you probably don't have access to
it. Ask your systems administrator(s) for details. If you don't have access
to news, you may still be able to post messages to the group by using a
mail server like anon.penet.fi (mail help@anon.penet.fi for more
information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu.
-------------------------------------------------------
>From domarkmk@aol.com (Domark MK)
Subject: Asynchronous File I-O
Date: 27 Jul 1995 23:54:02 -0400
Organization: America Online, Inc. (1-800-827-6364)
After many hours of wasted time today, I've learned that asynchronous file
I/O isn't possible on the Mac, at least until Apple rewrites the SCSI
Manager. I've heard that SCSI Manager 4.3 fixes that "for some machines",
but I have it installed and it's not having any effect, and I need it to
work for all machines (well, all PowerPC machines, including the upgrade
cards). I came across some code that makes async file calls from Time
Manager completion routines, and tried that, but of course everything
still stops as soon as the read is initiated and doesn't continue until
it's finished. I also found the async I/O Thread Manager code, but I
haven't tried it because I believe it will behave the same as the Time
Manager 'asynchronous' I/O.
All I want is to be able to read from a CD, while continuously drawing
stuff on the screen. (I'm playing an animation from the disk, using a
double-buffering technique that relies on asynchronous reads.) Is it
possible? Can it be done? Does anyone have a sledgehammer I can borrow?
Thanks,
Mike.
________________________________________________________________________
Michael A. Kelly Senior Software Engineer
mkelly@domark.com Domark Software, Inc.
________________________________________________________________________
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 29 Jul 1995 02:25:59 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <3v9n0q$gfr@newsbf02.news.aol.com> Domark MK, domarkmk@aol.com
writes:
>After many hours of wasted time today, I've learned that
>asynchronous file I/O isn't possible on the Mac, at least until
>Apple rewrites the SCSI Manager. I've heard that SCSI Manager
>4.3 fixes that "for some machines", but I have it installed and
>it's not having any effect, and I need it to work for all
>machines (well, all PowerPC machines, including the upgrade
>cards).
The File Manager handles asynchronous requests now (and always has).
However, there are certain limitations that make asynchronous File Manager
requests only semi-useful.
The first limitation is the Macintosh file system (and much of the rest of
the operating system) is currently single-threaded. That means that you
can have a dozen asynchronous requests outstanding but they execute one at
a time. The asynchronous requests that are waiting are kept in an OS
queue and are handled (except in the special cases of retries and to
remote AppleShare volumes) first in / first out.
The next limitation is that many device drivers and the SCSI Manager
before SCSI Manager 4.3 handle all requests synchronously. So, even
though the File Manager calls the device driver asynchronously (because
the File Manager request was made asynchronously), the device driver or
SCSI Manager doesn't return control to the file system until the call is
complete.
I guess a short overview of how the file system works might help here.
I'll use a Read as an example of what happens. I'm going to leave out
lots of the minor details, but you should get the general idea...
When you make a Read request to the File Manager, it looks at the trap
word and sets a flag for itself if the async bit is set. Then it continues
the handling of the Read; it makes sure the file is open with read access,
calculates the offset where the Read should begin, and calls the routine
that figures out where the file blocks to be read are on the disk.
Now, the File Manager is ready to read the data from the disk, so it needs
to call the disk driver that owns the volume to read 1 or more blocks.
The File Manager checks the "async" flag and if the File Manager request
was asynchronous, then it calls the disk driver asynchronously (with a
completion routine) to read the blocks; if the request was synchronous,
then it calls the disk driver synchronously.
If the call was made asynchronously, then when the File Manager gets
control back, it returns control to the code that made the original File
Manager request. Meanwhile, the disk driver reads the disk. When the disk
driver finishes and calls the completion routine, the File Manager has
control again and continues handling the Read request. (If more disk I/O
is needed, it is made asynchronously again.) When the File Manager has
fulfilled the Read request, it sets the result code in the parameter
block, it calls the completion routine for the asynchronous File Manager
request (if there was one), and then checks to see if it needs to start
handling another queued request. If not, control is returned to whatever
was interrupted.
As you can see, if the disk driver handles asynchronous requests to it
synchronously, then the program that called the File Manager
asynchronously never gets any time back before the call is complete.
Also, since the File Manager is single-threaded, a synchronous driver
blocks all queued calls behind it.
So, what works now? The AppleShare foreign file system has always handled
almost all calls asynchronously so your program can get control back while
your request is handled by an AppleShare file server. With SCSI Manager
4.3 and the proper asynchronous SCSI disk drivers on on all 040 and
PowerPC based systems.
So, why are asynchronous calls still useful, even when the disk driver is
synchronous? Because you can make asynchronous requests at interrupt time
without causing the file system to deadlock (if the file system is
handling a call and you interrupt it and make a synchronous file system
call, the file system can't finish what it's doing and can't give you
control back... that's deadlock).
I hope that kind of clears things up for you. When we get a multi-threaded
operating system on the Macintosh, things will be even better. You might
want to read the "develop" magazine article I wrote for issue #13 if you
can find it. It covers asynchronous programming techniques in detail.
- Jim Luther
+++++++++++++++++++++++++++
>From domarkmk@aol.com (Domark MK)
Date: 29 Jul 1995 17:13:05 -0400
Organization: America Online, Inc. (1-800-827-6364)
>>
SCSI Manager 4.3
provides asynchronous disk i/o, ASSUMING your driver supports asynchronous
disk i/o.
<<
OK, so when will I be able to assume that most everyone with a PowerMac
has drivers for their cd-roms that support asynchronous i/o? Is the
driver in the hardware or is it in the Apple CD-ROM extensions (or their
third-party substitutes)? Is there a new version of the Apple CD-ROM
extensions that support async i/o? If so, could I include it with my
software so that I could then assume they have a driver that supports
async i/o?
Or do I just have to reduce the quality of my animation because of the
limitations of prior versions of the system software? (As I see it, async
support would be standard in current drivers if the Mac OS had supported
it sooner.)
Mike.
________________________________________________________________________
Michael A. Kelly Senior Software Engineer
mkelly@domark.com Domark Software, Inc.
________________________________________________________________________
+++++++++++++++++++++++++++
>From blob@apple.com (Brian Bechtel)
Date: Sat, 29 Jul 1995 21:55:36 -0700
Organization: Apple Computer, Inc.
In article <3ve891$mjh@newsbf02.news.aol.com>, domarkmk@aol.com (Domark
MK) wrote:
> OK, so when will I be able to assume that most everyone with a PowerMac
> has drivers for their cd-roms that support asynchronous i/o?
I'm not sure anyone can answer this question...
>Is the driver in the hardware
No. The driver is the software which understands how to talk to the hardware.
>or is it in the Apple CD-ROM extensions (or their third-party substitutes)?
For the Apple CD-ROM software, the driver is called "Apple CD-ROM".
Apple's driver only supports Apple CD-ROM drives; you have to use third
party drivers for third party drives. Look at
http://www.info.apple.com/dev/devinfo/maccdromfaq.html#thirdparty
for some third party drivers.
>Is there a new version of the Apple CD-ROM extensions that support
>async i/o?
I'm not sure what versions didn't support asynchronous i/o, if any.
>If so, could I include it with my software so that I could then
> assume they have a driver that supports async i/o?
If you want to redistribute Apple software, you have to contact Apple's
software licensing department at sw.license@applelink.apple.com. You'll
have to contact the authors of third party software to find their
redistribution requirements.
--
--Brian Bechtel blob@apple.com Village Idiot, DTS
+++++++++++++++++++++++++++
>From domarkmk@aol.com (Domark MK)
Date: 1 Aug 1995 12:35:43 -0400
Organization: America Online, Inc. (1-800-827-6364)
>>Is there a new version of the Apple CD-ROM extensions that support
>>async i/o?
>
>I'm not sure what versions didn't support asynchronous i/o, if any.
Hmmm, so if I have SCSI Manager 4.3.1, and Apple CD-ROM 5.0.1, and an
Apple CD300, PBReadAsync should work asynchronously? It doesn't....
Could it be that the hardware doesn't support async i/o?
Mike.
________________________________________________________________________
Michael A. Kelly Senior Software Engineer
mkelly@domark.com Domark Software, Inc.
________________________________________________________________________
+++++++++++++++++++++++++++
>From domarkmk@aol.com (Domark MK)
Date: 1 Aug 1995 12:35:43 -0400
Organization: America Online, Inc. (1-800-827-6364)
>>Is there a new version of the Apple CD-ROM extensions that support
>>async i/o?
>
>I'm not sure what versions didn't support asynchronous i/o, if any.
Hmmm, so if I have SCSI Manager 4.3.1, and Apple CD-ROM 5.0.1, and an
Apple CD300, PBReadAsync should work asynchronously? It doesn't....
Could it be that the hardware doesn't support async i/o?
Mike.
________________________________________________________________________
Michael A. Kelly Senior Software Engineer
mkelly@domark.com Domark Software, Inc.
________________________________________________________________________
---------------------------
>From duncant@sushi.mitre.or.jp (Duncan Thomson)
Subject: Saving and restoring current drawing port - necessary?
Date: Thu, 20 Jul 1995 09:31:12 +0530
Organization: Nothing to do with my organization
Hi, Mac programming novice here with a question...
The "Inside Mac" books say that, before setting the current port (when you
want to draw in it), you should save the previous port, then, after you
are done drawing, set it back to what it was. (Written in a confusing
manner, I admit, but I think you know what I'm talking about.)
My question: Is this really necessary? If all code sets the port as
necessary before drawing in it, why bother to restore it? Is there some
problem with asynchronous processing going on here?
Thanks
Duncan
p.s. Please e-mail me your response, as well as posting (if you think it's
worth posting at all) as my news server is unreliable, and I may miss your
answer if you just post.
+++++++++++++++++++++++++++
>From peter@adi.co.nz (Peter Bromley)
Date: Fri, 21 Jul 1995 17:41:26 +1200
Organization: ADInstruments
In article <3umsqt$ocg@netnews.upenn.edu>, kurisuto@babel.ling.upenn.edu
(Sean Crist) wrote:
> In article <duncant-2007950931120001@a09.dial.twics.com>,
> Duncan Thomson <duncant@sushi.mitre.or.jp> wrote:
> >Hi, Mac programming novice here with a question...
> >
> >The "Inside Mac" books say that, before setting the current port (when you
> >want to draw in it), you should save the previous port, then, after you
> >are done drawing, set it back to what it was. (Written in a confusing
> >manner, I admit, but I think you know what I'm talking about.)
> >
> >My question: Is this really necessary? If all code sets the port as
> >necessary before drawing in it, why bother to restore it? Is there some
> >problem with asynchronous processing going on here?
>
> Well, I almost never do this, myself, and I've never had any problems. My
> personal programming policy is that it's every routine for itself as far as
> the port is concerned; if a routine is expecting the port to be
> such-and-such, it's that routine's responsibility to set it itself. This
> saves me from having to trace back through a dozen routines to see who
> changed the port.
>
As if its all that difficult to do the right thing. All you need to do is
use the GetPort, SetPort, code, SetPort combination as a response to the
following things
Events
(update, activate, mousedown, keydown, appleevent),
Internal program "events"
(idle, checkmouseshape, checknextWNEsleep, somedatachanged, dosomething)
If you do this right you need never set the port elsewhere (except to work
with offscreen bitmaps / printing / ... well, maybe some other times) :-)
> I _might_ make an exception (i.e. and save and restore the port) if I had
> some routine which did drawing in a certain port and was frequently called
> from within other routines which needed the port to be something in
> particular, so that calling this drawing routine would be transparent. But
> in practice I find that I never need to do this.
>
See, if you did it _right_, you wouldnt ever need to protect individual
routines ever.
BTW: If IM says do something, you'ld have to be a fool or an expert to do
otherwise (IMO of course).
--
Peter Bromley (peter@adi.co.nz)
ADInstruments, Dunedin, New Zealand
+++++++++++++++++++++++++++
>From pandhphot@aol.com (PandH Phot)
Date: 20 Jul 1995 20:16:40 -0400
Organization: America Online, Inc. (1-800-827-6364)
You'll find that often the current port is the monitor's "world". If you
don't restore it and somebody tries to write to the monitor, bad things
might happen. If you're always using modal dialogs you might get away with
it, since they rule the world while they live and die oblivious to their
neighbors, but I'm not even sure I'd count on that in the brave new
permanent-Multifinder society we live in.
Besides, it's so easy, why fight it?
Paul
+++++++++++++++++++++++++++
>From kurisuto@babel.ling.upenn.edu (Sean Crist)
Date: 21 Jul 1995 12:10:43 GMT
Organization: University of Pennsylvania, Linguistics Department
In article <peter-2107951741260001@adi008.adi.co.nz>,
Peter Bromley <peter@adi.co.nz> wrote:
>In article <3umsqt$ocg@netnews.upenn.edu>, kurisuto@babel.ling.upenn.edu
>(Sean Crist) wrote:
>> Well, I almost never do this, myself, and I've never had any problems. My
>> personal programming policy is that it's every routine for itself as far as
>> the port is concerned; if a routine is expecting the port to be
>> such-and-such, it's that routine's responsibility to set it itself. This
>> saves me from having to trace back through a dozen routines to see who
>> changed the port.
>
>As if its all that difficult to do the right thing. All you need to do is
>use the GetPort, SetPort, code, SetPort combination as a response to the
>following things
*shrug* I wasn't aware that this was an issue on which there is a "right"
way to do things. Your way works, but I don't see what's wrong with my
way, as it works too, and doesn't violate any of Apple's rules (I think
they included GetPort so that you _can_ preserve the port, not because you
_have_ to).
Really, I think it's personal preference, and the important thing is that
you pick a scheme and then _be consistant_ with it. Since none of my
routines make assumptions about what the port should be (with a very few
exceptions which I always document clearly in my comments), none of them
need to preserve it either, and I never run into trouble.
>> I _might_ make an exception (i.e. and save and restore the port) if I had
>> some routine which did drawing in a certain port and was frequently called
>> from within other routines which needed the port to be something in
>> particular, so that calling this drawing routine would be transparent. But
>> in practice I find that I never need to do this.
>
>See, if you did it _right_, you wouldnt ever need to protect individual
>routines ever.
>
>BTW: If IM says do something, you'ld have to be a fool or an expert to do
>otherwise (IMO of course).
I agree that IM should be rigorously followed. But I don't agree that I'm
outside IM's rules here. I'd be quite shocked to learn that IM somewhere
says "If your routines change the port internally, they must always
remember and restore the current port, and if you don't do this, your
application is likely to break under future system releases." The
important point is that the port be correctly set at times when it matters,
and there's more than one overall scheme for ensuring that this is so.
\/ __ __ _\_ --Sean Crist (kurisuto@unagi.cis.upenn.edu)
--- | | \ /
_| ,| ,| ----- For a free copy of the Bill of Rights, finger
_| ,| ,| [_] this account.
| | | [_]
+++++++++++++++++++++++++++
>From kurisuto@babel.ling.upenn.edu (Sean Crist)
Date: 21 Jul 1995 00:36:45 GMT
Organization: University of Pennsylvania, Linguistics Department
In article <duncant-2007950931120001@a09.dial.twics.com>,
Duncan Thomson <duncant@sushi.mitre.or.jp> wrote:
>Hi, Mac programming novice here with a question...
>
>The "Inside Mac" books say that, before setting the current port (when you
>want to draw in it), you should save the previous port, then, after you
>are done drawing, set it back to what it was. (Written in a confusing
>manner, I admit, but I think you know what I'm talking about.)
>
>My question: Is this really necessary? If all code sets the port as
>necessary before drawing in it, why bother to restore it? Is there some
>problem with asynchronous processing going on here?
Well, I almost never do this, myself, and I've never had any problems. My
personal programming policy is that it's every routine for itself as far as
the port is concerned; if a routine is expecting the port to be
such-and-such, it's that routine's responsibility to set it itself. This
saves me from having to trace back through a dozen routines to see who
changed the port.
I _might_ make an exception (i.e. and save and restore the port) if I had
some routine which did drawing in a certain port and was frequently called
from within other routines which needed the port to be something in
particular, so that calling this drawing routine would be transparent. But
in practice I find that I never need to do this.
\/ __ __ _\_ --Sean Crist (kurisuto@unagi.cis.upenn.edu)
--- | | \ /
_| ,| ,| ----- For a free copy of the Bill of Rights, finger
_| ,| ,| [_] this account.
| | | [_]
+++++++++++++++++++++++++++
>From Charles B. Cranston <zben@ni.umd.edu>
Date: 21 Jul 1995 18:22:23 GMT
Organization: Network Infrastructures UMD CSC
> Is it really necessary to save and restore the current port
> and set the desired port before and after any drawing?
I've used both philosophies:
1. "Every routine for himself" - religiously set the port before any
drawing, the current port is irrelevant at any other time.
2. "Keep the port set to the frontmost window" - religiosly set the
current port every activate, deactivate etc.
I remember back in the pre-Multifinder days (System 6) there was a
Mac Tech Note describing a gotcha situation between applications and
desk accessories (which USED to run in application space but were
moved to Finder's space in Multifinder and System 7).
In the worst case, two badly coded DAs could crash each other without
the application being able to do anything about it! But there were
other cases of DA vs application crashes that could be avoided if you
made sure there was a valid current port befor giving the DA time.
I don't think this can happen anymore. Anybody know?
+-+-+
Charles B. (Ben) Cranston <zben@ni.umd.edu>
http://www.wam.umd.edu/~zben
+++++++++++++++++++++++++++
>From mouser@zercom.net (Martin-Gilles Lavoie)
Date: 24 Jul 1995 16:23:32 GMT
Organization: zercom technologies inc.
In article <3uor8v$3b6@mimsy.cs.umd.edu>, Charles B. Cranston
<zben@ni.umd.edu> wrote:
> > Is it really necessary to save and restore the current port
> > and set the desired port before and after any drawing?
>
> I've used both philosophies:
>
> 1. "Every routine for himself" - religiously set the port before any
> drawing, the current port is irrelevant at any other time.
>
> 2. "Keep the port set to the frontmost window" - religiosly set the
> current port every activate, deactivate etc.
>
> I remember back in the pre-Multifinder days (System 6) there was a
> Mac Tech Note describing a gotcha situation between applications and
> desk accessories (which USED to run in application space but were
> moved to Finder's space in Multifinder and System 7).
>
> In the worst case, two badly coded DAs could crash each other without
> the application being able to do anything about it! But there were
> other cases of DA vs application crashes that could be avoided if you
> made sure there was a valid current port befor giving the DA time.
>
> I don't think this can happen anymore. Anybody know?
>
I've had extensions crewing up my view ports now and then. Some still
do. I dont take a chance. As to setting the port to every
activate/deactivate events. this may be overkill (although, it doesn't
take much CPU time..). To be safe, I always set my port before drawing.
On activate, it'd be only usefull if I wanted to track the cursor position
relative to the window position.
--
Martin-Gilles Lavoie
MPW: Because life is too complicated for CodeWarrior.
--MGL
+++++++++++++++++++++++++++
>From peter@adi.co.nz (Peter Bromley)
Date: Sun, 23 Jul 1995 15:40:53 +1200
Organization: ADInstruments
In article <3uo5g3$kbm@netnews.upenn.edu>, kurisuto@babel.ling.upenn.edu
(Sean Crist) wrote:
> In article <peter-2107951741260001@adi008.adi.co.nz>,
> Peter Bromley <peter@adi.co.nz> wrote:
> >In article <3umsqt$ocg@netnews.upenn.edu>, kurisuto@babel.ling.upenn.edu
> >(Sean Crist) wrote:
>
> >> Well, I almost never do this, myself, and I've never had any problems. My
> >> personal programming policy is that it's every routine for itself as far as
> >> the port is concerned; if a routine is expecting the port to be
> >> such-and-such, it's that routine's responsibility to set it itself. This
> >> saves me from having to trace back through a dozen routines to see who
> >> changed the port.
> >
> >As if its all that difficult to do the right thing. All you need to do is
> >use the GetPort, SetPort, code, SetPort combination as a response to the
> >following things
>
> *shrug* I wasn't aware that this was an issue on which there is a "right"
> way to do things. Your way works, but I don't see what's wrong with my
> way, as it works too, and doesn't violate any of Apple's rules (I think
> they included GetPort so that you _can_ preserve the port, not because you
> _have_ to).
>
Hmmmm, I guess I didnt express myself very clearly. And perhaps you are
right - the NIM snippets dont seem to advocate protecting the current port
at all. I guess my approach has arisin from discovering that whenever I
found a current port related bug (like system font getting trashed, or
LocalToGlobal doing weird things) I found that the port was not what I
expected. My code policy evolved out from that to the (I guess) paranoid,
but safe approach of making sure the port is what I want it to be but -
just in case - always restoring the current port as well. I found it was
easier to do this as close to my main event loop as possible and got the
added bonus that lower level routines could assume the port was always
correct.
BTW: these problems dont just come up with regard to the current port. I
still find it difficult to setle on _one_ scheme for lots of other things,
like pen and text settings within a port, foreground colour, and so on.
The situation gets trickier, too, when you're not the only one working on
a program. Differing approaches can cause lots of obscure bugs in a
multi-person project ;-)
--
Peter Bromley (peter@adi.co.nz)
ADInstruments, Dunedin, New Zealand
+++++++++++++++++++++++++++
>From Richard Wesley <hawkfish@punchdeck.com>
Date: 23 Jul 1995 23:28:17 GMT
Organization: Punch Deck Consulting
peter@adi.co.nz (Peter Bromley) wrote:
>In article <3umsqt$ocg@netnews.upenn.edu>, kurisuto@babel.ling.upenn.edu
>(Sean Crist) wrote:
>
>> In article <duncant-2007950931120001@a09.dial.twics.com>,
>> Duncan Thomson <duncant@sushi.mitre.or.jp> wrote:
>> >Hi, Mac programming novice here with a question...
>> >
>> >The "Inside Mac" books say that, before setting the current port (when you
>> >want to draw in it), you should save the previous port, then, after you
>> >are done drawing, set it back to what it was. (Written in a confusing
>> >manner, I admit, but I think you know what I'm talking about.)
>> >
>> >My question: Is this really necessary? If all code sets the port as
>> >necessary before drawing in it, why bother to restore it? Is there some
>> >problem with asynchronous processing going on here?
>>
>> Well, I almost never do this, myself, and I've never had any problems. My
>> personal programming policy is that it's every routine for itself as far as
>> the port is concerned; if a routine is expecting the port to be
>> such-and-such, it's that routine's responsibility to set it itself. This
>> saves me from having to trace back through a dozen routines to see who
>> changed the port.
>>
>
>As if its all that difficult to do the right thing. All you need to do is
>use the GetPort, SetPort, code, SetPort combination as a response to the
>following things
>
>Events
> (update, activate, mousedown, keydown, appleevent),
>Internal program "events"
> (idle, checkmouseshape, checknextWNEsleep, somedatachanged, dosomething)
>
If you're using CW PowerPlant, you can even use the utility class StPortOriginState to save the state, then all you have to do is is=
sue a declaration and C++ will clean it all up for you (even if an exception is thrown.)
If you're not using PP, just do something like
class StPortState {
GrafPtr mSave;
public:
StPortState (GrafPtr inPort) {::GetPort (&mSave); ::SetPort (inPort);};
~StPortState (void) {::SetPort (mSave);};
};
and say
StPortState savePort (myPort);
at the top of your routine. No muss no fuss.
- rmgw
http://www.punchdeck.com/hawkfish/PunchDeck.html
- --------------------------------------------------------------------------
Richard Wesley hawkfish@punchdeck.com | "'Hand it round first, and cut it
Punch Deck Consulting pnchdeck@aol.com | afterwards.'" - Lewis Carroll,
Macintosh Software Development | "Through the Looking Glass"
- --------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From thor@telerama.lm.com (Tom Moertel)
Date: Mon, 24 Jul 1995 22:50:05 -0500
Organization: Management Science Associates, Commercial Software Group
Regarding the age-old controversy of whether or not to save and restore
the drawing environment, I look to a higher question: Sould we know where
we are drawing?
The obvious answer is yes. We ought to know where we are drawing. To
draw haphazardly is to discard order and consistency, to cast away the
foundation of the Macintosh environment. Thus we create The Fundamental
Axiom of Drawing: We should always know where we are drawing.
Now, can we derive from the Axiom simple rules ensuring that our code will
always do the right thing? You betcha.
*** Rule 1 *** Before drawing in an independent routine, explicitly set
the drawing environment.
Rule 1 ensures that when your routine draws, it knows where it is drawing.
But we still have a problem. What about the routine that called your
drawing routine? When your routine returns, how can we ensure that the
caller will still be drawing where it thinks it is? Rule 2 gives the
answer:
*** Rule 2 *** If your routine changes the drawing environment, make sure
it restores the environment before returning to the caller.
Rule 2 ensures that if the caller knew where it was drawing when it called
your routine, it will still know where it is drawing when it regains
control (because it is drawing in the same place).
These two rules are sufficient to ensure consistency with the Fundamental
Axiom. If you follow them, your code will always draw in the right place,
and the world will be more enjoyable for all.
--
Tom Moertel
thor@telerama.lm.com
+++++++++++++++++++++++++++
>From carl.gustafson@ece.drexel.edu (Carl Gustafson)
Date: 24 Jul 1995 13:21:42 GMT
Organization: Imaging and Computer Vision Center, Drexel University
In article <peter-2307951540530001@adi008.adi.co.nz>, peter@adi.co.nz
(Peter Bromley) wrote:
> Hmmmm, I guess I didnt express myself very clearly. And perhaps you are
> right - the NIM snippets dont seem to advocate protecting the current port
> at all. I guess my approach has arisin from discovering that whenever I
> found a current port related bug (like system font getting trashed, or
> LocalToGlobal doing weird things) I found that the port was not what I
> expected. My code policy evolved out from that to the (I guess) paranoid,
> but safe approach of making sure the port is what I want it to be but -
> just in case - always restoring the current port as well. I found it was
> easier to do this as close to my main event loop as possible and got the
> added bonus that lower level routines could assume the port was always
> correct.
>
> BTW: these problems dont just come up with regard to the current port. I
> still find it difficult to setle on _one_ scheme for lots of other things,
> like pen and text settings within a port, foreground colour, and so on.
> The situation gets trickier, too, when you're not the only one working on
> a program. Differing approaches can cause lots of obscure bugs in a
> multi-person project ;-)
I've always considered preserving and restoring the grafport, pen
settings, handle lock settings, etc. to be good, defensive programming.
(Mostly defensive against myself, but that's another matter.) It may be a
PITA to develop the habit, and take an extra minute to paste in the code,
but it can save much cleanup time later.
--
Carl Gustafson
Imaging and Computer Vision Center
Drexel University, Philadelphia, Penna
- ----------------------------------------------------------
I don't speak for Drexel, and Drexel doesn't listen to me...
+++++++++++++++++++++++++++
>From Jim.Spencer@p510.f61.n282.z1.fidonet.org (Jim Spencer)
Date: 23 Jul 95 10:58:27
Organization: Magical Mystery
On 7/21/95, kurisuto@babel.ling.upenn.edu emerged from Plato's cave and
expounded the following to All
ku> *shrug* I wasn't aware that this was an issue on which there is a
ku> "right" way to do things. Your way works, but I don't see what's
ku> wrong with my way, as it works too, and doesn't violate any of Apple's
ku> rules (I think they included GetPort so that you _can_ preserve the
ku> port, not because you _have_ to).
No, there is a right way. Your code is not the only one using QuickDraw, the
toolbox itself is if no one else.
ku> Really, I think it's personal preference, and the important thing is
ku> that you pick a scheme and then _be consistant_ with it. Since none
ku> of my routines make assumptions about what the port should be (with a
ku> very few exceptions which I always document clearly in my comments),
ku> none of them need to preserve it either, and I never run into trouble.
Until the toolbox thinks that the port is set to one thing and in fact it's
set
to another then CRASH.
> I _might_ make an exception (i.e. and save and restore the port) if I
> had some routine which did drawing in a certain port and was frequently
> called from within other routines which needed the port to be something
> in particular, so that calling this drawing routine would be
> transparent. But in practice I find that I never need to do this.
>
> See, if you did it _right_, you wouldnt ever need to protect individual
> routines ever.
>
> BTW: If IM says do something, you'ld have to be a fool or an expert to
> do otherwise (IMO of course).
>
ku> I agree that IM should be rigorously followed. But I don't agree that
ku> I'm outside IM's rules here. I'd be quite shocked to learn that IM
ku> somewhere says "If your routines change the port internally, they must
ku> always remember and restore the current port, and if you don't do
ku> this, your application is likely to break under future system
ku> releases." The important point is that the port be correctly set at
ku> times when it matters, and there's more than one overall scheme for
ku> ensuring that this is so.
This issue is the same as checking for errors. It's a question of how bullet
proof you want your code to be. If you restore the port in your drawing
functions then it doesn't matter what happens elsewhere. You are making
assumptions which at best can only be called sloppy in particular that you
won't make a mistake as your code get's more complicated (I'll grant you this
isn't much of an issue in a "Hello World!" program but how about in something
exceeding 100,000 lines??) and that no one other than you will ever work with
your code. IMHO, you can only be sure that both will be true if you are
doing
essentially trivial programs.
+++++++++++++++++++++++++++
>From peter@adi.co.nz (Peter Bromley)
Date: Wed, 26 Jul 1995 18:51:11 +1200
Organization: ADInstruments
In article <mouser-2407951158400001@204.191.6.123>, mouser@zercom.net
(Martin-Gilles Lavoie) wrote:
[SNIP]
>
> I've had extensions crewing up my view ports now and then....
Ouch!!!
> ... Some still
> do. I dont take a chance. As to setting the port to every
> activate/deactivate events. this may be overkill (although, it doesn't
> take much CPU time..). To be safe, I always set my port before drawing.
> On activate, it'd be only usefull if I wanted to track the cursor position
> relative to the window position.
>
One of the most common reactions to (de)activate is to add or remove a
selection (esp calling TEActivate). The current port needs to be set
correctly for these things to draw right (although TEActivate might be
paranoid)
Just another $0.02,
--
Peter Bromley (peter@adi.co.nz)
ADInstruments, Dunedin, New Zealand
+++++++++++++++++++++++++++
>From peter@stairways.com.au (Peter N Lewis)
Date: Thu, 27 Jul 1995 20:07:41 +0800
Organization: Stairways Software
In article <thor-2407952250050001@thor.slip.lm.com>, thor@telerama.lm.com
(Tom Moertel) wrote:
>The obvious answer is yes. We ought to know where we are drawing. To
>draw haphazardly is to discard order and consistency, to cast away the
>foundation of the Macintosh environment. Thus we create The Fundamental
>Axiom of Drawing: We should always know where we are drawing.
>*** Rule 1 *** Before drawing in an independent routine, explicitly set
>the drawing environment.
>*** Rule 2 *** If your routine changes the drawing environment, make sure
>it restores the environment before returning to the caller.
Rule 2 is redundant and not necessary (and ignoring it leads to Sean
Crist's way of doing it (which is the same as mine, and contrary to
popular wisdom).
If you draw something, ensure the port is set correctly (Rule 1). If you
call another routine which may change the port, then re-apply Rule 1.
Obviously, if you are messing around with trap patching and the like, then
you want to preserve *everything*. Also, if you are in a library routine
that shouldn't be messing with the port, but does in strange cases, or a
callback from the OS or something like that where the caller is out of
your control, then it is defnsive to restore the port.
However, it is not necessarily safe to do so. For example, consider this code:
wp := NewWindow
SetPort(wp)
CloseWindow(wp)
CallYourRoutine
If CallYourRoutine does as suggested by popular wisdom, then it will save
and restore the port - but the port is currently invalid, so the trailing
SetPort(savedport) call will be invalid and potentially dangerous! More
important than Rule 2 is that you should never call SetPort (or any other
OS routine) with invalid parameters.
Enjoy,
Peter.
--
It's still easy in Unix:
ls *.lisp | sed -e 's/\(.*\).lisp$/mv "\1.lisp" "\1.lst"/' | sh
--Tim Smith <tzs@u.washington.edu>
+++++++++++++++++++++++++++
>From thor@telerama.lm.com (Tom Moertel)
Date: Fri, 28 Jul 1995 00:49:15 -0500
Organization: Management Science Associates, Commercial Software Group
In article <peter-2707952007420001@zany.peter.com.au>,
peter@stairways.com.au (Peter N Lewis) wrote:
> In article <thor-2407952250050001@thor.slip.lm.com>, thor@telerama.lm.com
> (Tom Moertel) wrote:
>
> > [SNIP] Thus we create The Fundamental
> > Axiom of Drawing: We should always know where we are drawing.
>
> >*** Rule 1 *** Before drawing in an independent routine, explicitly set
> >the drawing environment.
>
> >*** Rule 2 *** If your routine changes the drawing environment, make sure
> >it restores the environment before returning to the caller.
>
> Rule 2 is redundant and not necessary (and ignoring it leads to Sean
> Crist's way of doing it (which is the same as mine, and contrary to
> popular wisdom).
>
> If you draw something, ensure the port is set correctly (Rule 1). If you
> call another routine which may change the port, then re-apply Rule 1.
If I call a routine that I suspect will muck up the drawing environment, I
do as you suggest and re-apply rule 1. That's defensive programming.
However, I draw the line at repeatedly applying rule 1 as my primary
method of esuring that my code is drawing in the right place with the
right settings. There are three reasons for my preference:
(1) Applying Rule 1 can be costly. If a routine has special requirements
for the pen, text face, text size, and so on, repeatedly enforcing
those requirements can be excessive.
(2) Because of (1), we might be tempted to examine a subroutine before
calling it just to see what parts of the graphics environment it
changes, in hopes of have to restore only those parts. Our calling
routine would thus become dependent on the implementation details
of the subroutine. I try to reduce dependancy when possible.
(3) Alternatively, we could try to reduce the costs mentioned in (1)
by having overly graphic subroutines clean up after themselves (in
essence, applying Rule 2). In that way, callers would need to re-apply
Rule 1 only to the more commonly changed graphics variables. I
don't like this arrangement because it's inconsistent. Sometimes
we use a re-application of Rule 1 and sometimes we use Rule 1 in
conjunction with Rule 2. That's too confusing for my meager
brain to handle in the midnight hours, when otherwise good hackin'
might be disrupted by too much thinkin' ;-)
> Obviously, if you are messing around with trap patching and the like, then
> you want to preserve *everything*. Also, if you are in a library routine
> that shouldn't be messing with the port, but does in strange cases, or a
> callback from the OS or something like that where the caller is out of
> your control, then it is defnsive to restore the port.
>
> However, it is not necessarily safe to do so. For example, consider
this code:
>
> wp := NewWindow
> SetPort(wp)
> CloseWindow(wp)
> CallYourRoutine
>
> If CallYourRoutine does as suggested by popular wisdom, then it will save
> and restore the port - but the port is currently invalid, so the trailing
> SetPort(savedport) call will be invalid and potentially dangerous!
Hey, that's not fair! ;-) The way I see it, you could remove
CallYourRoutine altogether and the port will still be hosed. That is,
unless you think it's a good idea to have CallYourRoutine, a subroutine,
set up its caller's port as a side effect of its normal operation.
In this case it's clear that if the program wants to draw after it called
CloseWindow, it had better set up the drawing environment -- regardless of
what CallYourRoutine does. What's interesting is that even in this
example, where the port is hosed, CallYourRoutine would have drawn
properly if it been written with both Rule 1 and Rule 2 in mind.
> More
> important than Rule 2 is that you should never call SetPort (or any other
> OS routine) with invalid parameters.
Agreed. But it's hard to ensure that your parameters will always be good
without the help of a couple rules....
Cheers and fine homebrew,
Tom
--
Tom Moertel
thor@telerama.lm.com
+++++++++++++++++++++++++++
>From Mark Williams <Mark@streetly.demon.co.uk>
Date: Thu, 27 Jul 95 09:37:56 GMT
Organization: Streetly Software
In article <c1b_9507250800@mmbbs.com>, Jim Spencer writes:
>
> On 7/21/95, kurisuto@babel.ling.upenn.edu emerged from Plato's cave and
> expounded the following to All
>
> ku> *shrug* I wasn't aware that this was an issue on which there is a
> ku> "right" way to do things. Your way works, but I don't see what's
> ku> wrong with my way, as it works too, and doesn't violate any of Apple's
> ku> rules (I think they included GetPort so that you _can_ preserve the
> ku> port, not because you _have_ to).
>
> No, there is a right way. Your code is not the only one using QuickDraw, the
> toolbox itself is if no one else.
>
> ku> Really, I think it's personal preference, and the important thing is
> ku> that you pick a scheme and then _be consistant_ with it. Since none
> ku> of my routines make assumptions about what the port should be (with a
> ku> very few exceptions which I always document clearly in my comments),
> ku> none of them need to preserve it either, and I never run into trouble.
>
> Until the toolbox thinks that the port is set to one thing and in fact it's
> set
> to another then CRASH.
Well, the only toolbox call I can think of which requires a particular port to be set (other than
the obvious quickdraw calls) is ModalDialog, and thats always struck me as a mistake in the
documentation - last time I checked it operates on the FrontWindow() not the current port, BWTFDIK.
I suppose the exceptions are callback routines and DefProcs - but here the documentation is
(usually) very specific about what you need to save and restore.
That objection aside (please dont bother sending me lists of toolbox calls which require a
particular port to be set), I still dont follow the logic here. There _are_ times when a certain
port needs to be set - so you just set it. What has that got to do with saving and restoring the
port?
Look at the way PowerPlant and TCL (and possibly MacApp - I wouldnt know) handle setting the port.
There is a routine (Prepare, or FocusView - whatever) which sets up the port and coordinate system.
It gets called whenever a particular view needs to be setup - the frameworks make no attempt to save
the current port. More significantly, since all the views in a window share a single port, _just_
saving and restoring the port will do you no good at all - you lose the origin, clipping region and
any other view-specific environment info (font, pen size, colours etc).
>
> [snip]
> This issue is the same as checking for errors. It's a question of how bullet
>
> proof you want your code to be. If you restore the port in your drawing
> functions then it doesn't matter what happens elsewhere. You are making
> assumptions which at best can only be called sloppy in particular that you
> won't make a mistake as your code get's more complicated (I'll grant you this
> isn't much of an issue in a "Hello World!" program but how about in something
> exceeding 100,000 lines??) and that no one other than you will ever work with
> your code. IMHO, you can only be sure that both will be true if you are
> doing
> essentially trivial programs.
Wow.
All TCL and PowerPlant apps are trivial.
- --------------------------------------
Mark Williams<Mark@streetly.demon.co.uk>
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D’Oliveiro)
Date: Fri, 28 Jul 1995 19:53:13 +1200
Organization: University of Waikato
In article <peter-2707952007420001@zany.peter.com.au>,
peter@stairways.com.au (Peter N Lewis) wrote:
>However, it is not necessarily safe to do so. For example, consider this code:
>
>wp := NewWindow
>SetPort(wp)
>CloseWindow(wp)
>CallYourRoutine
>
>If CallYourRoutine does as suggested by popular wisdom, then it will save
>and restore the port - but the port is currently invalid, so the trailing
>SetPort(savedport) call will be invalid and potentially dangerous!
I disagree. I don't think there is anything wrong with doing a SetPort to
an invalid port, just so long as you don't try to draw to it. And if every
piece of code is explicitly doing a SetPort before doing their drawing,
you'll never hit the problem!
Consider also what happens after the initial InitGraf call: the current
port is undefined then, too.
In short, it seems to me the current semantics of SetPort is: it's OK to
use it to restore whatever value you previously got from GetPort, even if
that value is not a valid port. Somehow I don't think that aspect of the
semantics will ever change, since it just makes things too complicated
otherwise.
Lawrence "QuickDraw GX doesn't have this problem" D'Oliveiro
+++++++++++++++++++++++++++
>From stk@berlin.snafu.de (Stefan Kurth)
Date: Fri, 28 Jul 1995 13:22:43 +0200
Organization: none
Peter N Lewis <peter@stairways.com.au> wrote:
> In article <thor-2407952250050001@thor.slip.lm.com>, thor@telerama.lm.com
> (Tom Moertel) wrote:
>
> >*** Rule 1 *** Before drawing in an independent routine, explicitly set
> >the drawing environment.
>
> >*** Rule 2 *** If your routine changes the drawing environment, make sure
> >it restores the environment before returning to the caller.
>
> Rule 2 is redundant and not necessary (and ignoring it leads to Sean
> Crist's way of doing it (which is the same as mine, and contrary to
> popular wisdom).
>
> If you draw something, ensure the port is set correctly (Rule 1). If you
> call another routine which may change the port, then re-apply Rule 1.
Peter, I can't believe that you wrote this. No offence, but this has
very little to do with modern programming techniques. It requires that
for every routine that you call you have to know whether it can possibly
change the current port. This is not desirable, especially in multi-
person projects.
A much better design is to make sure that none of your routines have any
side effects whatsoever, like changing global variables, or changing the
drawing environment or the current port (which is just a global variable
after all).
Suppose you have something like this:
SetPort(myWindow);
/* draw something here */
SomeRoutine();
/* draw something else here */
You don't set the port again after SomeRoutine(), because you know that
this routine doesn't change the port. Now, 1/2 year later you make
modifications to SomeRoutine so that it now does change the current port
for some reason (or calls another routine that does). So you now have
to go through your entire program, find all calls to SomeRoutine, and
insert SetPort's all over the place. Frankly, I wouldn't want to have
to maintain your program.
> wp := NewWindow
> SetPort(wp)
> CloseWindow(wp)
> CallYourRoutine
>
> If CallYourRoutine does as suggested by popular wisdom, then it will save
> and restore the port - but the port is currently invalid, so the trailing
> SetPort(savedport) call will be invalid and potentially dangerous! More
> important than Rule 2 is that you should never call SetPort (or any other
> OS routine) with invalid parameters.
There is nothing to worry about here. Invalid parameter? Maybe, but we
got that parameter from GetPort earlier, so it must be valid enough for
the OS. And whether the port was valid before we were called, or will
be valid after we return, is not something we should care about. We
just set everything back to what it was, and this is no more dangerous
than if we hadn't been called at all.
The only place where you would have to worry about the port being
invalid is in the routine that calls CloseWindow, but nowhere else.
________________________________________________________________________
Stefan Kurth Berlin, Germany stk@berlin.snafu.de
+++++++++++++++++++++++++++
>From mhl@icf.hrb.com (Mark H. Linton)
Date: 27 Jul 95 18:00:55 EST
Organization: HRB Systems, Inc.
In article <thor-2407952250050001@thor.slip.lm.com>,
thor@telerama.lm.com (Tom Moertel) wrote:
>Thus we create The Fundamental Axiom of Drawing:
> We should always know where we are drawing.
>
>*** Rule 1 *** Before drawing in an independent routine, explicitly set
>the drawing environment.
>
>*** Rule 2 *** If your routine changes the drawing environment, make sure
>it restores the environment before returning to the caller.
>
I am afraid I agree with Tom on this.
Just to get all of you who are less than defensive, I am going to
write an extension which installs a global jGNE filter -- whose
only purpose in life is to:
a) screw up the current graphics port (i.e. set it to something
other than it was before)
b) screw up the graphics pen (e.g., set its width to 32768 x
32768, etc.)
If your screen doesn't get wacky, then your coding technique
obviously works. Otherwise not...
BTW, the suggested Get, Set, Draw, Set sequence will always work
in a cooperative multitasking environment in the presence of such
a filter.
--
Hope this helps.
Mark H. Linton
____________________________________________________________________
mark \'märk\ n [ME, fr. OE mearc boundary, march, sign; akin to OHG
marha boundary, L margo] 1 a : a conspicuous object serving as a guide
for travelers 2 : A standard or criterion of quality 3 : An object or
point that serves as a guide --idiom. mark time. 1 : To make little or
no progress
+++++++++++++++++++++++++++
>From pottier@jonque.ens.fr (Francois Pottier)
Date: 28 Jul 1995 15:10:19 GMT
Organization: Ecole Normale Superieure, Paris
In article <thor-2807950049150001@thor.slip.lm.com>,
Tom Moertel <thor@telerama.lm.com> wrote:
>(1) Applying Rule 1 can be costly. If a routine has special requirements
> for the pen, text face, text size, and so on, repeatedly enforcing
> those requirements can be excessive.
>
>(2) Because of (1), we might be tempted to examine a subroutine before
> calling it just to see what parts of the graphics environment it
> changes, in hopes of have to restore only those parts.
I understand these problems. I suggest you have a look at the way they
are handled in PowerPlant. PowerPlant only uses Rule 1. This means that
no assumptions are made about the current port, and a routine has to
set the graphic environment by calling FocusDraw() before drawing.
So a PowerPlant program ends up calling FocusDraw() many times. But
the implementation of FocusDraw() remembers if it has already been
called, so it costs almost nothing to call it too often. I think it's
a good solution.
--
Francois Pottier pottier@dmi.ens.fr
- ----------------------------------------------------------------------------
Check my WWW page at http://acacia.ens.fr:8080/home/pottier/ ...
+++++++++++++++++++++++++++
>From pottier@jonque.ens.fr (Francois Pottier)
Date: 28 Jul 1995 15:15:55 GMT
Organization: Ecole Normale Superieure, Paris
In article <1995072813224396868@stk.berlin.snafu.de>,
Stefan Kurth <stk@berlin.snafu.de> wrote:
>> If you draw something, ensure the port is set correctly (Rule 1). If you
>> call another routine which may change the port, then re-apply Rule 1.
>
>Peter, I can't believe that you wrote this. No offence, but this has
>very little to do with modern programming techniques. It requires that
>for every routine that you call you have to know whether it can possibly
>change the current port. This is not desirable, especially in multi-
>person projects.
I agree that it is not desirable - but it is *not* necessary. Just
assume that *every* subroutine changes the port. Always set it before
drawing.
As I pointed out in another message, setting the graphics environment
every time you think it might have changed is not costly if you have
a smart implementation. Look at PowerPlant - it remembers which pane
is currently in focus.
About the port being invalid, it's nothing to worry about, as long as
you apply rule 1 and set it before drawing.
Cheers,
--
Francois Pottier pottier@dmi.ens.fr
- ----------------------------------------------------------------------------
Check my WWW page at http://acacia.ens.fr:8080/home/pottier/ ...
+++++++++++++++++++++++++++
>From ingemar@lysator.liu.se (Ingemar Ragnemalm)
Date: 29 Jul 1995 19:22:39 GMT
Organization: (none)
>>> Duncan Thomson <duncant@sushi.mitre.or.jp> wrote:
>>> >Hi, Mac programming novice here with a question...
>>> >
>>> >The "Inside Mac" books say that, before setting the current port (when you
>>> >want to draw in it), you should save the previous port, then, after you
>>> >are done drawing, set it back to what it was. (Written in a confusing
>>> >manner, I admit, but I think you know what I'm talking about.)
>>> >
>>> >My question: Is this really necessary? If all code sets the port as
>>> >necessary before drawing in it, why bother to restore it? Is there some
>>> >problem with asynchronous processing going on here?
No, you don't HAVE to restore the port, but it is a very good habit. If all
utility functions, routines that fire up dialogs etc, restore the port, you
can call them any time. If you are careless, you will have to put SetPort's
all over the place.
--
- -
Ingemar Ragnemalm, PhD
Image processing, Mac shareware games
E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se
+++++++++++++++++++++++++++
>From kenp@nmrfam.wisc.edu (Ken Prehoda)
Date: Tue, 01 Aug 1995 10:00:42 -0500
Organization: Univ of Wisc-Madison, Dept of Biochemistry
In article <ldo-2807951953130001@130.217.96.144>, ldo@waikato.ac.nz wrote:
: In article <peter-2707952007420001@zany.peter.com.au>,
: peter@stairways.com.au (Peter N Lewis) wrote:
:
: >However, it is not necessarily safe to do so. For example, consider
this code:
: >
: >wp := NewWindow
: >SetPort(wp)
: >CloseWindow(wp)
: >CallYourRoutine
: >
: >If CallYourRoutine does as suggested by popular wisdom, then it will save
: >and restore the port - but the port is currently invalid, so the trailing
: >SetPort(savedport) call will be invalid and potentially dangerous!
:
: I disagree. I don't think there is anything wrong with doing a SetPort to
: an invalid port, just so long as you don't try to draw to it. And if every
: piece of code is explicitly doing a SetPort before doing their drawing,
: you'll never hit the problem!
:
: Consider also what happens after the initial InitGraf call: the current
: port is undefined then, too.
:
: In short, it seems to me the current semantics of SetPort is: it's OK to
: use it to restore whatever value you previously got from GetPort, even if
: that value is not a valid port. Somehow I don't think that aspect of the
: semantics will ever change, since it just makes things too complicated
: otherwise.
:
: Lawrence "QuickDraw GX doesn't have this problem" D'Oliveiro
It all depends on how you use Quickdraw GX. If you use the:
gxRectangle rectGeom = {...};
gxShape rect = GXNewRectangle(&rectGeom);
GXSetShapeViewPorts(rect,...);
method, then sure you don't have to worry about the "current port". But
there is the disadvantage of creating an object in the GX heap that you
could potentially leave around for awhile.
GX also has these types of calls though:
gxRectangle rectGeom = {...};
GXDrawRectangle(&rectGeom,...);
and if you use these types, then you certainly do have to worry about the
"current port" (or default shapes as they are called in GX). It is also
interesting to note that these calls are quite a bit faster than the ones
given in the above example.
--
Ken Prehoda, kenp@nmrfam.wisc.edu
+++++++++++++++++++++++++++
>From kenp@nmrfam.wisc.edu (Ken Prehoda)
Date: Tue, 01 Aug 1995 10:00:42 -0500
Organization: Univ of Wisc-Madison, Dept of Biochemistry
In article <ldo-2807951953130001@130.217.96.144>, ldo@waikato.ac.nz wrote:
: In article <peter-2707952007420001@zany.peter.com.au>,
: peter@stairways.com.au (Peter N Lewis) wrote:
:
: >However, it is not necessarily safe to do so. For example, consider
this code:
: >
: >wp := NewWindow
: >SetPort(wp)
: >CloseWindow(wp)
: >CallYourRoutine
: >
: >If CallYourRoutine does as suggested by popular wisdom, then it will save
: >and restore the port - but the port is currently invalid, so the trailing
: >SetPort(savedport) call will be invalid and potentially dangerous!
:
: I disagree. I don't think there is anything wrong with doing a SetPort to
: an invalid port, just so long as you don't try to draw to it. And if every
: piece of code is explicitly doing a SetPort before doing their drawing,
: you'll never hit the problem!
:
: Consider also what happens after the initial InitGraf call: the current
: port is undefined then, too.
:
: In short, it seems to me the current semantics of SetPort is: it's OK to
: use it to restore whatever value you previously got from GetPort, even if
: that value is not a valid port. Somehow I don't think that aspect of the
: semantics will ever change, since it just makes things too complicated
: otherwise.
:
: Lawrence "QuickDraw GX doesn't have this problem" D'Oliveiro
It all depends on how you use Quickdraw GX. If you use the:
gxRectangle rectGeom = {...};
gxShape rect = GXNewRectangle(&rectGeom);
GXSetShapeViewPorts(rect,...);
method, then sure you don't have to worry about the "current port". But
there is the disadvantage of creating an object in the GX heap that you
could potentially leave around for awhile.
GX also has these types of calls though:
gxRectangle rectGeom = {...};
GXDrawRectangle(&rectGeom,...);
and if you use these types, then you certainly do have to worry about the
"current port" (or default shapes as they are called in GX). It is also
interesting to note that these calls are quite a bit faster than the ones
given in the above example.
--
Ken Prehoda, kenp@nmrfam.wisc.edu
---------------------------
>From tmorrow@us.oracle.com (tmorrow)
Subject: Where are my command line arguments?
Date: 29 Jul 1995 00:19:26 GMT
Organization: Oracle Corporation. Redwood Shores, CA
We are in the process of porting some batch programs over to the
Macintosh from UNIX, and realizing that the Mac has no command line
argument interface for invoking executables.
This is a major bummer, and are curious about what other people have
done in this type of situation.
We basically have one program which sequentially spawns processes to do
various batch type tasks, communicating important paramters to the
child processes through the command line. We have thought of using
files to communicate the same information that we communicated on the
command line in UNIX. The files would be the documents in Mac's
document-centric interface; invoking (opening) a file of command line
arguments would be equivalent to invoking an application with those
command line arguments on UNIX. Another idea would be apple events,
but that would probably require even more "nativising" which we don't
want to do if we don't have to.
Is there some kind of library or some other simple solution that won't
require as much native coding as using files of arguments or passing
the arguments through apple events? Ideally there would be a way to
keep the argc, argv processing code just the way it is on UNIX.
It seems like a glaring deficiency that the Mac has no way of passing
paramters to an application upon startup, but I guess that is due to
its document-centric design, eh?
Please copy me via email if you respond.
Thanks!
-Tom Morrow
tmorrow@us.oracle.com
+++++++++++++++++++++++++++
>From fesh@applelink.apple.com (TheBug)
Date: 29 Jul 1995 13:30:30 GMT
Organization: privat
In article <3vbuqe$cpc@inet-nntp-gw-1.us.oracle.com>,
tmorrow@us.oracle.com (tmorrow) wrote:
> We are in the process of porting some batch programs over to the
> Macintosh from UNIX, and realizing that the Mac has no command line
> argument interface for invoking executables.
>
> This is a major bummer, and are curious about what other people have
> done in this type of situation.
>
> We basically have one program which sequentially spawns processes to do
> various batch type tasks, communicating important paramters to the
> child processes through the command line. We have thought of using
> files to communicate the same information that we communicated on the
> command line in UNIX. The files would be the documents in Mac's
> document-centric interface; invoking (opening) a file of command line
> arguments would be equivalent to invoking an application with those
> command line arguments on UNIX. Another idea would be apple events,
> but that would probably require even more "nativising" which we don't
> want to do if we don't have to.
>
> Is there some kind of library or some other simple solution that won't
> require as much native coding as using files of arguments or passing
> the arguments through apple events? Ideally there would be a way to
> keep the argc, argv processing code just the way it is on UNIX.
>
> It seems like a glaring deficiency that the Mac has no way of passing
> paramters to an application upon startup, but I guess that is due to
> its document-centric design, eh?
Hope you intend to use this only in-house and have no intention to sell
it. If you try to sell such a solution to the Mac community I would rather
suggest to stop right now and not waste your energy. Any magazine review
of such a program would be a bad bashing up.
If this program is for end user sales you will have to go the full way and
make it a real Mac application, otherwise you will get buried in the
market. Mac users are kind of allergic to "cheap ports".
If this is just for in-house use you should get yourself MPW from Apple.
This is basically a development environment but it offers you standard
command line interfacing with argc, argv, output redirection and all the
stuff.
+++++++++++++++++++++++++++
>From Richard Wesley <hawkfish@punchdeck.com>
Date: 29 Jul 1995 16:02:37 GMT
Organization: Punch Deck Consulting
tmorrow@us.oracle.com (tmorrow) wrote:
>
>We are in the process of porting some batch programs over to the
>Macintosh from UNIX, and realizing that the Mac has no command line
>argument interface for invoking executables.
>
>This is a major bummer, and are curious about what other people have
>done in this type of situation.
>
>We basically have one program which sequentially spawns processes to do
>various batch type tasks, communicating important paramters to the
>child processes through the command line. We have thought of using
>files to communicate the same information that we communicated on the
>command line in UNIX. The files would be the documents in Mac's
>document-centric interface; invoking (opening) a file of command line
>arguments would be equivalent to invoking an application with those
>command line arguments on UNIX. Another idea would be apple events,
>but that would probably require even more "nativising" which we don't
>want to do if we don't have to.
>
>Is there some kind of library or some other simple solution that won't
>require as much native coding as using files of arguments or passing
>the arguments through apple events? Ideally there would be a way to
>keep the argc, argv processing code just the way it is on UNIX.
>
>It seems like a glaring deficiency that the Mac has no way of passing
>paramters to an application upon startup, but I guess that is due to
>its document-centric design, eh?
There _is_ a way to do this - AppleEvents. All you have to do
is define your own AE that passes a command line. Then you can write one
bottleneck routine that takes a process name and a command line and
launches the process with the given AE. Each process then just needs a
shell that recieves the AE and breaks it up for your "main".
- rmgw
http://www.punchdeck.com/hawkfish/PunchDeck.html
- --------------------------------------------------------------------------
Richard Wesley hawkfish@punchdeck.com | "'Hand it round first, and cut it
Punch Deck Consulting pnchdeck@aol.com | afterwards.'" - Lewis Carroll,
Macintosh Software Development | "Through the Looking Glass"
- --------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From 3gl21@qlink.queensu.ca (Gregory Lo)
Date: Sat, 29 Jul 1995 22:13:25 -0400
Organization: Queen's University
In article <3vbuqe$cpc@inet-nntp-gw-1.us.oracle.com>,
tmorrow@us.oracle.com (tmorrow) wrote:
> We are in the process of porting some batch programs over to the
> Macintosh from UNIX, and realizing that the Mac has no command line
> argument interface for invoking executables.
> We basically have one program which sequentially spawns processes to do
> various batch type tasks, communicating important paramters to the
> child processes through the command line. We have thought of using
> files to communicate the same information that we communicated on the
> command line in UNIX. The files would be the documents in Mac's
> document-centric interface; invoking (opening) a file of command line
> arguments would be equivalent to invoking an application with those
> command line arguments on UNIX.
Don't do this. No Mac end-user would ever want to bother with this hassle.
> Another idea would be apple events,
> but that would probably require even more "nativising" which we don't
> want to do if we don't have to.
This is the way to go. (You would recieve Apple Events, anyway)
Apple Events are _the_ medium of interapplication communication in MacOS.
Their use is standard and necessary for later versions of MacOS.
> Is there some kind of library or some other simple solution that won't
> require as much native coding as using files of arguments or passing
> the arguments through apple events? Ideally there would be a way to
> keep the argc, argv processing code just the way it is on UNIX.
Most commercial compilers will include console interfaces and libraries to
ease porting of programs from other platforms. Or, you could use MPW, but
then your program could only be used from within the MPW environment.
> It seems like a glaring deficiency that the Mac has no way of passing
> paramters to an application upon startup, but I guess that is due to
> its document-centric design, eh?
Actually, you _do_ get information passed to your application upon startup
anyway via one of three of the four _required_ Apple Events: "Open
Application", "Open Document(s)", "Print Document(s)".
Creating files and then opening them as a means of passing parameters ends
up creating and sending "Open Document" Apple Events, anyway. If your
application were properly written for MacOS, it should be no trouble to
extend to the use of other Apple Events. I'm sure there are libraries and
frameworks to make this incredibly easy for you.
A third alternative is to make use of threads. Threads operate similiarly
on almost all platforms and OS' that support them. Your UN*X probably
supports the use of threads. Beware, though, that pre-emptive threads in
MacOS are now only supported on 68K machines, using System 7.5 or later,
or using System 7.1 with the Thread Manager extension.
GLo
ps. I've never really considered the Mac as a document-centric interface.
I just don't see how it would differ from other OS' (like UN*X) in that
respect. OLE and OpenDoc, I would consider document-centric interfaces.
- ---------------------------------------------------------
Gregory Lo GLo ?:^(> <mailto:3gl21@qlink.queensu.ca>
+++++++++++++++++++++++++++
>From ckt@best.com (Chris Thomas)
Date: Sat, 29 Jul 1995 20:36:29 -0800
Organization: Echo Software
In article <fesh-2907951530280001@async107.zrz.tu-berlin.de>,
fesh@applelink.apple.com (TheBug) wrote:
> In article <3vbuqe$cpc@inet-nntp-gw-1.us.oracle.com>,
> tmorrow@us.oracle.com (tmorrow) wrote:
>
> > We are in the process of porting some batch programs over to the
> > Macintosh from UNIX, and realizing that the Mac has no command line
> > argument interface for invoking executables.
> >
> > This is a major bummer, and are curious about what other people have
> > done in this type of situation.
> >
> > We basically have one program which sequentially spawns processes to do
> > various batch type tasks, communicating important paramters to the
> > child processes through the command line. We have thought of using
> > files to communicate the same information that we communicated on the
> > command line in UNIX. The files would be the documents in Mac's
> > document-centric interface; invoking (opening) a file of command line
> > arguments would be equivalent to invoking an application with those
> > command line arguments on UNIX. Another idea would be apple events,
> > but that would probably require even more "nativising" which we don't
> > want to do if we don't have to.
> >
> > Is there some kind of library or some other simple solution that won't
> > require as much native coding as using files of arguments or passing
> > the arguments through apple events? Ideally there would be a way to
> > keep the argc, argv processing code just the way it is on UNIX.
> >
> > It seems like a glaring deficiency that the Mac has no way of passing
> > paramters to an application upon startup, but I guess that is due to
> > its document-centric design, eh?
>
> Hope you intend to use this only in-house and have no intention to sell
> it. If you try to sell such a solution to the Mac community I would rather
> suggest to stop right now and not waste your energy. Any magazine review
> of such a program would be a bad bashing up.
>
> If this program is for end user sales you will have to go the full way and
> make it a real Mac application, otherwise you will get buried in the
> market. Mac users are kind of allergic to "cheap ports".
>
> If this is just for in-house use you should get yourself MPW from Apple.
> This is basically a development environment but it offers you standard
> command line interfacing with argc, argv, output redirection and all the
> stuff.
Also, don't forget that the AppleEvent manager *is* the Mac version
of command-line arguments- difference being that AppleEvents are
highly typed. You'll have to nativize if you expect to reap the
benefits of the Macintosh architecture.
--
Chris Thomas, ckt@best.com
+++++++++++++++++++++++++++
>From jthill@netcom.com (Jim Hill)
Date: Sun, 30 Jul 1995 06:39:45 GMT
Organization: biological <-- hey! a one-word oxymoron!
In article <3vbuqe$cpc@inet-nntp-gw-1.us.oracle.com>,
tmorrow@us.oracle.com (tmorrow) wrote:
>We are in the process of porting some batch programs over to the
>Macintosh from UNIX, and realizing that the Mac has no command line
>argument interface for invoking executables.
I think Greg Lo hit the nail on the head; this is just another take on the
same idea.
There are lots of ways to do what you want, but as you've noticed they're
all different from what UNIX does, and (csmp.misc guys, come on, let's
admit this) it's a pain in the butt when you're porting. But as Greg
pointed out, if you don't do the work you don't have a Mac program, and if
Mac users see it they'll leave you on the shelf.
When launching programs, you can specify an apple event to feed them on
startup. It can be anything you want. You can build it yourself, get it
from a document, whatever. You wrote the code on both ends, so if you're
really into not porting you can just make up a command-line apple event;
it'll be the first thing your code sees and if I recall the Oracle coding
guidelines correctly you've got an s0-prefix main on every one of them
anyway.
Given time, I'd go farther and just bypass out the command-line processing
completely, using appleevents instead: run transactions that have the
parameters already digested and a list of docs (or whatever) to run them
on, and have both the unix cmdline parsing and mac appleevent breakout
drive exactly the same processing code.
Just riffing,
Jim
obStuffIApologizeForNotDeleting:
At any rate, IM-Processes has lots of good stuff along these lines. Try
scripting a UNIX process sometime :-) -- "expect" is a gross, limited
hack. I guess that is due to UNIX's keyboard-centric design, eh? ;-)
--
Jim Hill Contents public domain and worth $.02 more than you paid.
jthill@netcom.com PGPrint: 6B 85 76 D1 EF BA 2C 78 12 25 8A 5A BF F3 37 7E
+++++++++++++++++++++++++++
>From Manuel Veloso <veloso@RT66.com>
Date: 1 Aug 1995 14:58:07 GMT
Organization: Ibex Productions
In article <3vbuqe$cpc@inet-nntp-gw-1.us.oracle.com> tmorrow,
tmorrow@us.oracle.com writes:
>Is there some kind of library or some other simple solution that won't
>require as much native coding as using files of arguments or passing
>the arguments through apple events? Ideally there would be a way to
>keep the argc, argv processing code just the way it is on UNIX.
>
Well, if it's not going to be public, how about using MPW?
You guys probably have a copy in-house somewhere.
The only downsides are that you can't launch a tool from another
tool, and everything's linear (ie: tool/script/tool/tool).
Another option is to applescript it, with each batch program being
an OSAXen and an applescript being the makefile/driver equivalent.
Putting a shell around your programs that extracts params from
the AppleEvents, transforms them into argv/argc, and returns values
shouldn't be that hard.
Manuel
+++++++++++++++++++++++++++
>From Manuel Veloso <veloso@RT66.com>
Date: 1 Aug 1995 14:58:07 GMT
Organization: Ibex Productions
In article <3vbuqe$cpc@inet-nntp-gw-1.us.oracle.com> tmorrow,
tmorrow@us.oracle.com writes:
>Is there some kind of library or some other simple solution that won't
>require as much native coding as using files of arguments or passing
>the arguments through apple events? Ideally there would be a way to
>keep the argc, argv processing code just the way it is on UNIX.
>
Well, if it's not going to be public, how about using MPW?
You guys probably have a copy in-house somewhere.
The only downsides are that you can't launch a tool from another
tool, and everything's linear (ie: tool/script/tool/tool).
Another option is to applescript it, with each batch program being
an OSAXen and an applescript being the makefile/driver equivalent.
Putting a shell around your programs that extracts params from
the AppleEvents, transforms them into argv/argc, and returns values
shouldn't be that hard.
Manuel
---------------------------
End of C.S.M.P. Digest
**********************